大家對於 DevTools 還熟悉嗎?專屬於 Flutter 的 Debugging 工具,本身也是使用 Flutter 進行開發,以這工具來看,就可以知道 Flutter 淺力了對吧,順暢表現當然沒問題。不過這是題外話,就我的觀察與了解,大部分開發者不太熟悉它,很多人比較常用 Inspector,查看排版佈局以及定位元件,其他很多功能都沒在使用,但它們卻非常重要也很有價值。
本文就是要帶大家了解 DevTools,逐步說明 Flutter Inspector 以及 Performance 工具,如何幫助我們開發以及優化產品,附上非常多的實際操作流程以及範例,希望讓大家更有感覺,並開始擁抱和喜歡使用它們。
APP 的每一幀創建和渲染在各別的線程上運行,分別是 UI Thread 和 Raster Thread,如果要避免延遲,需在16毫秒或更短的時間內創建、處理並顯示一幀,才能期望一秒達成 60 幀。如果發現 APP 總渲染時間低於16毫秒,即使存在一些效能缺陷,也不必擔心,因為可能不會產生視覺差異,比較難感受出來。隨著近幾年 120fps 設備的普及,就需要8毫秒內完成渲染流程,以提供最流暢的體驗,而在順暢的運行下也可以有效改善電池壽命和散熱問題。
在 Flutter 裡,官方提供了 DevTools 工具協助我們開發,那什麼情境下需要使用工具來優化 APP 呢?
其中幾點情況你的 APP 有遇到嗎?有的話是不是要考慮優化專案了?我們趕緊往下邊閱讀邊操作吧!
在學會使用工具之前,需要先了解 Flutter 幾種專案的運行模式,每個模式適合的情境都不同
適合開發階段
flutter run --debug
# flavor
flutter run --debug --flavor dev --target ./lib/main_dev.dart
適合分析性能、效能調教
flutter run --profile
適合正式產品
tree-shaking
壓縮資源檔案,實現運行時的效能最優化。因此,APP容量最小,可以快速啟動、處理運算flutter run --release
以下範例,我針對 Column 做了調整,動了 DecoratedBox 和 AppGap 兩個元件的配置,當我調整後,右邊的 UI 也即時更新,可以再確認效果後再去改程式碼就好。
顯示渲染框,根據元件的重繪次數顯示不一樣的顏色,註記那些會頻繁重繪的範圍。在每次重繪時有刷新的元件線條顏色會一直變換,如果此時有看到不應該重繪的元件頻繁更新顏色,就代表程式碼需要優化,嚴重的話會影響 APP 效能表現。
以下方範例來看,點擊的選項顏色與外框都會比較突出,所以選擇後會根據狀態更新新舊兩個元件,這時候會看到有兩個元件的外框顏色在變化,其他不相關的部分會保持原本顏色,也代表沒有無意義更新。
如果不想開啟 DevTools 也可以在主函式 main()
設置 debugRepaintRainbowEnabled 為 true,需要匯入 rendering.dart
。
debugRepaintRainbowEnabled = false;
標示大型圖像,通過顏色反轉和顛倒來標示體積過大、使用大量記憶體的圖像。不管是本地圖像還是雲端圖像都可以檢測。如果有使用到很長的 ScrollView,當大量大體積圖像載入時,可能會有效能表現的影響。
多大的體積,會被標記為大型圖像呢?超出 debugImageOverheadAllowance 設置大小,預設為128kb
當發現大型圖像時 Console 也會看到 Painting Exception。以下範例顯示,元件實際的寬長為 852×563 但是卻解析了 1179×786 尺寸的圖像,同時也給予了建議,可以設置 cacheWidth、cacheHeight,或是使用 ResizeImage 優化。
如果不想開啟 DevTools 也可以在主函式 main()
設置 debugInvertOversizedImages 為 true。
debugInvertOversizedImages = true
當然也可以設置圖片的允許大小,透過 debugImageOverheadAllowance 進行調整。下方範例調整為 256kb,不過實際上要評估普遍用戶的裝置類型與記憶體使用來設置,太大反而是個風險。
debugImageOverheadAllowance = 256 * 1024;
右邊有告知每個顏色所代表的資訊:
幀分析。查看當前幀的 UI 與 Raster 處理時間,以下方範例來看,就是 Raster 部分特別耗時。以經驗來看可能跟顯示圖片、圖像有關
渲染光柵狀態。針對當下取得快照,了解當前幀的詳細資訊,包含被處理的每個元素、渲染時間、每個元素佔的總體比例。
實際在 Flutter Rendering Pipeline 裡 RenderObject Tree 會轉為 Layer Tree,接著交給 Compositor 將每個 Layer 組合起來並匯出圖層,詳細可以留到其他文章來討論。所以畫面上才會顯示第幾 Layer。
以範例來看,確實最耗時的部分為顯示圖片,接下來可以根據這點進一步確認相關程式碼,進行檢驗和優化。
注意:右上角的刷新按鈕,很容易會造成卡頓和網頁崩潰,可能因為資料量太大無法及時處理,這部分可以等待優化。
在 Flutter 可以使用 Timeline 計算事件的運作時間
Timeline.startSync("tag")
...
Timeline.finishSync()
針對 Timeline Events 進行更詳細的追蹤,可以開啟 Widget Builds、Layouts、Paints 三種模式。也因為要追蹤更多數據,所以開啟後可能會影響 APP 的運行表現,幀數可能下降。
從中也可以更了解 Rendering Pipeline 的整個過程,Build、Layout、Paint、Compositing、Finalize Tree,接著到 GPU 的 Rasterizing 處理。
可以清楚了解這一幀 build 的結果,瀏覽 Widget Tree。
追蹤佈局排版,所以會看到 RenderBox、RenderPadding、RenderFlex 等等相關角色。
追蹤繪製過程中的相關資訊。
檢查有關裁剪的相關操作,例如:ClipRRect。屬於昂貴任務,尤其是對於 Skia 圖形引擎 ,濫用可能會造成掉幀、卡頓。
檢查不透明效果的相關操作,例如:Opacity、BackdropFilter。屬於昂貴、高成本任務。
檢查使用 Physical Shape 陰影效果的操作,例如:Shadow、Elevation。濫用也有可能造成效能影響。
以上三個操作對於 Skia 來說成本較高,請適當地使用它們,而對於新的 Impeller 引擎的負擔就小很多,可以等待 Android 穩定釋出,再來觀察整體效能表現。相關細節可以查看其他文章,有關開發技巧,以下是連結:
本文從說明何謂 APP 順暢、性能影響因素,再到個別工具的使用,讓大家可以搭配圖片與實際範例更好地去理解。身為開發者都應該懂的如何使用它們,開發過程中使用 Inspector 協助檢查畫面結構與元件細節。接著,在產品需求完成後,可以花一點時間使用 Performance 確認實際的 release 表現,幀數是否正常,是否有 Jank 發生,持續地改善產品,讓使用者有個完美體驗,這應該是開發者都要注重的環節。
DevTools 本身很強大,它的價值可不要忽略囉!